home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / program / 317 / asmsrc / atof-gen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-10-20  |  15.2 KB  |  494 lines

  1. /* atof_generic.c - */
  2.  
  3. /* Copyright (C) 1987 Free Software Foundation, Inc.
  4.  
  5. This file is part of Gas, the GNU Assembler.
  6.  
  7. The GNU assembler is distributed in the hope that it will be
  8. useful, but WITHOUT ANY WARRANTY.  No author or distributor
  9. accepts responsibility to anyone for the consequences of using it
  10. or for whether it serves any particular purpose or works at all,
  11. unless he says so in writing.  Refer to the GNU Assembler General
  12. Public License for full details.
  13.  
  14. Everyone is granted permission to copy, modify and redistribute
  15. the GNU Assembler, but only under the conditions described in the
  16. GNU Assembler General Public License.  A copy of this license is
  17. supposed to have been given to you along with the GNU Assembler
  18. so you can know your rights and responsibilities.  It should be
  19. in a file named COPYING.  Among other things, the copyright
  20. notice and this notice must be preserved on all copies.  */
  21.  
  22. #include <ctype.h>
  23. #include "flonum.h"
  24. #ifdef sparc
  25. #include <alloca.h>
  26. #endif
  27.  
  28. #define    FALSE (0)
  29. #define TRUE  (1)
  30.  
  31. char *index();
  32.  
  33. /***********************************************************************\
  34. *                                    *
  35. *    Given a string of decimal digits , with optional decimal    *
  36. *    mark and optional decimal exponent (place value) of the        *
  37. *    lowest_order decimal digit: produce a floating point        *
  38. *    number. The number is 'generic' floating point: our        *
  39. *    caller will encode it for a specific machine architecture.    *
  40. *                                    *
  41. *    Assumptions                            *
  42. *        uses base (radix) 2                    *
  43. *        this machine uses 2's complement binary integers    *
  44. *        target flonums use "      "         "       "        *
  45. *        target flonums exponents fit in a long int        *
  46. *                                    *
  47. \***********************************************************************/
  48.  
  49. /*
  50.  
  51.             Syntax:
  52.  
  53. <flonum>        ::=    <optional-sign> <decimal-number> <optional-exponent>
  54. <optional-sign>        ::=    '+' | '-' | {empty}
  55. <decimal-number>    ::=      <integer>
  56.                 | <integer> <radix-character> 
  57.                 | <integer> <radix-character> <integer> 
  58.                 |        <radix-character> <integer>
  59. <optional-exponent>    ::=    {empty} | <exponent-character> <optional-sign> <integer> 
  60. <integer>        ::=    <digit> | <digit> <integer>
  61. <digit>            ::=    '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
  62. <exponent-character>    ::=    {one character from "string_of_decimal_exponent_marks"}
  63. <radix-character>    ::=    {one character from "string_of_decimal_marks"}
  64.  
  65. */
  66.  
  67. int                /* 0 if OK */
  68.  
  69. atof_generic (
  70.     address_of_string_pointer, /* return pointer to just AFTER number we read. */
  71.     string_of_decimal_marks, /* At most one per number. */
  72.     string_of_decimal_exponent_marks,
  73.     address_of_generic_floating_point_number)
  74.  
  75.      char * *        address_of_string_pointer;
  76.      char *        string_of_decimal_marks;
  77.      char *        string_of_decimal_exponent_marks;
  78.      FLONUM_TYPE *    address_of_generic_floating_point_number;
  79.  
  80. {
  81.  
  82.   int            return_value; /* 0 means OK. */
  83.   char *        first_digit;
  84.   /* char *        last_digit; JF unused */
  85.   int            number_of_digits_before_decimal;
  86.   int            number_of_digits_after_decimal;
  87.   long int        decimal_exponent;
  88.   int            number_of_digits_available;
  89.   char            digits_sign_char;
  90.  
  91.   {
  92.     /*
  93.      * Scan the input string, abstracting (1)digits (2)decimal mark (3) exponent.
  94.      * It would be simpler to modify the string, but we don't; just to be nice
  95.      * to caller.
  96.      * We need to know how many digits we have, so we can allocate space for
  97.      * the digits' value.
  98.      */
  99.  
  100.     char *        p;
  101.     char        c;
  102.     int            seen_significant_digit;
  103.  
  104.     first_digit = * address_of_string_pointer;
  105.     c= *first_digit;
  106.     if (c=='-' || c=='+')
  107.       {
  108.     digits_sign_char = c;
  109.         first_digit ++;
  110.       }
  111.     else
  112.       {
  113.     digits_sign_char = '+';
  114.       }
  115.     number_of_digits_before_decimal = 0;
  116.     number_of_digits_after_decimal = 0;
  117.     decimal_exponent = 0;
  118.     seen_significant_digit = FALSE;
  119.     for (p = first_digit;
  120.      (c = * p)
  121.      && (!c || ! index (string_of_decimal_marks,          c) )
  122.      && (!c || ! index (string_of_decimal_exponent_marks, c) );
  123.      p ++)
  124.       {
  125.     if (isdigit(c))
  126.       {
  127.         if (seen_significant_digit || c > '0')
  128.           {
  129.         number_of_digits_before_decimal ++;
  130.         seen_significant_digit = TRUE;
  131.           }
  132.         else
  133.           {
  134.             first_digit++;
  135.           }
  136.       }
  137.     else
  138.       {
  139.         break;        /* p -> char after pre-decimal digits. */
  140.       }
  141.       }                /* For each digit before decimal mark. */
  142.     if (c && index (string_of_decimal_marks, c))
  143.       {
  144.     for (p ++;
  145.          (c = * p)
  146.          && (!c || ! index (string_of_decimal_exponent_marks, c) );
  147.          p ++)
  148.       {
  149.         if (isdigit(c))
  150.           {
  151.         number_of_digits_after_decimal ++; /* This may be retracted below. */
  152.         if (/* seen_significant_digit || */ c > '0')
  153.           {
  154.             seen_significant_digit = TRUE;
  155.           }
  156.           }
  157.         else
  158.           {
  159.         if ( ! seen_significant_digit)
  160.           {
  161.             number_of_digits_after_decimal = 0;
  162.           }
  163.         break;
  164.           }
  165.       }            /* For each digit after decimal mark. */
  166.       }
  167. /*    last_digit = p; JF unused */
  168.     
  169.     if (c && index (string_of_decimal_exponent_marks, c) )
  170.       {
  171.     char        digits_exponent_sign_char;
  172.     
  173.     c = * ++ p;
  174.     if (c && index ("+-",c))
  175.       {
  176.         digits_exponent_sign_char = c;
  177.         c = * ++ p;
  178.       }
  179.     else
  180.       {
  181.         digits_exponent_sign_char = '+';
  182.       }
  183.     for (;
  184.          (c);
  185.          c = * ++ p)
  186.       {
  187.         if (isdigit(c))
  188.           {
  189.         decimal_exponent = decimal_exponent * 10 + c - '0';
  190.         /*
  191.          * BUG! If we overflow here, we lose!
  192.          */
  193.           }
  194.         else
  195.           {
  196.         break;
  197.           }
  198.       }
  199.     if (digits_exponent_sign_char == '-')
  200.       {
  201.         decimal_exponent = - decimal_exponent;
  202.       }
  203.       }
  204.     * address_of_string_pointer = p;
  205.   }
  206.  
  207.   number_of_digits_available =
  208.     number_of_digits_before_decimal
  209.       + number_of_digits_after_decimal;
  210.   return_value = 0;
  211.   if (number_of_digits_available == 0)
  212.     {
  213.       address_of_generic_floating_point_number -> exponent = 0;    /* Not strictly necessary */
  214.       address_of_generic_floating_point_number -> leader
  215.     = -1 + address_of_generic_floating_point_number -> low;
  216.       address_of_generic_floating_point_number -> sign = digits_sign_char;
  217.       /* We have just concocted (+/-)0.0E0 */
  218.     }
  219.   else
  220.     {
  221.       LITTLENUM_TYPE *    digits_binary_low;
  222.       int        precision;
  223.       int        maximum_useful_digits;
  224.       int        number_of_digits_to_use;
  225.       int        more_than_enough_bits_for_digits;
  226.       int        more_than_enough_littlenums_for_digits;
  227.       int        size_of_digits_in_littlenums;
  228.       int        size_of_digits_in_chars;
  229.       FLONUM_TYPE    power_of_10_flonum;
  230.       FLONUM_TYPE    digits_flonum;
  231.  
  232.  
  233.       precision = (address_of_generic_floating_point_number -> high
  234.            - address_of_generic_floating_point_number -> low
  235.            + 1
  236.            )        /* Number of destination littlenums. */
  237.     + 2;            /* + 2 :: guard bits :: excess precision */
  238.       maximum_useful_digits = (  ((double) (precision - 2))
  239.                    * ((double) (LITTLENUM_NUMBER_OF_BITS))
  240.                    / (LOG_TO_BASE_2_OF_10)
  241.                    )
  242.     + 2;            /* 2 :: guard digits. */
  243.       if (number_of_digits_available > maximum_useful_digits)
  244.     {
  245.       number_of_digits_to_use = maximum_useful_digits;
  246.     }
  247.       else
  248.     {
  249.       number_of_digits_to_use = number_of_digits_available;
  250.     }
  251.       decimal_exponent += number_of_digits_before_decimal - number_of_digits_to_use;
  252.  
  253.       more_than_enough_bits_for_digits
  254.     = ((((double)number_of_digits_to_use) * LOG_TO_BASE_2_OF_10) + 1);
  255.       more_than_enough_littlenums_for_digits
  256.     = (  more_than_enough_bits_for_digits
  257.        / LITTLENUM_NUMBER_OF_BITS
  258.        )
  259.       + 2;
  260.       
  261.       /*
  262.        * Compute (digits) part. In "12.34E56" this is the "1234" part.
  263.        * Arithmetic is exact here. If no digits are supplied then
  264.        * this part is a 0 valued binary integer.
  265.        * Allocate room to build up the binary number as littlenums.
  266.        * We want this memory to disappear when we leave this function.
  267.        * Assume no alignment problems => (room for n objects) ==
  268.        * n * (room for 1 object).
  269.        */
  270.       
  271.       size_of_digits_in_littlenums = more_than_enough_littlenums_for_digits;
  272.       size_of_digits_in_chars = size_of_digits_in_littlenums
  273.     * sizeof( LITTLENUM_TYPE );
  274.       digits_binary_low = (LITTLENUM_TYPE *)
  275.     alloca (size_of_digits_in_chars);
  276.       bzero ((char *)digits_binary_low, size_of_digits_in_chars);
  277.  
  278.       /* Digits_binary_low[] is allocated and zeroed. */
  279.       
  280.       {
  281.     /*
  282.      * Parse the decimal digits as if * digits_low was in the units position.
  283.      * Emit a binary number into digits_binary_low[].
  284.      *
  285.      * Use a large-precision version of:
  286.      * (((1st-digit) * 10 + 2nd-digit) * 10 + 3rd-digit ...) * 10 + last-digit
  287.      */
  288.  
  289.     char *        p;
  290.     char        c;
  291.     int        count;    /* Number of useful digits left to scan. */
  292.  
  293.     for (p = first_digit, count = number_of_digits_to_use;
  294.          count;
  295.          p ++,  -- count)
  296.       {
  297.         c = * p;
  298.         if (isdigit(c))
  299.           {
  300.         /*
  301.          * Multiply by 10. Assume can never overflow.
  302.          * Add this digit to digits_binary_low[].
  303.          */
  304.  
  305.         long int    carry;
  306.         LITTLENUM_TYPE *    littlenum_pointer;
  307.         LITTLENUM_TYPE *    littlenum_limit;
  308.  
  309.         littlenum_limit
  310.           =     digits_binary_low
  311.             +   more_than_enough_littlenums_for_digits
  312.               - 1;
  313.         carry = c - '0';    /* char -> binary */
  314.         for (littlenum_pointer = digits_binary_low;
  315.              littlenum_pointer <= littlenum_limit;
  316.              littlenum_pointer ++)
  317.           {
  318.             long int    work;
  319.             
  320.             work = carry + 10 * * littlenum_pointer;
  321.             * littlenum_pointer = work & LITTLENUM_MASK;
  322.             carry = work >> LITTLENUM_NUMBER_OF_BITS;
  323.           }
  324.         if (carry != 0)
  325.           {
  326.             /*
  327.              * We have a GROSS internal error.
  328.              * This should never happen.
  329.              */
  330.             abort();    /* RMS prefers abort() to any message. */
  331.           }
  332.           }
  333.         else
  334.           {
  335.         ++ count;    /* '.' doesn't alter digits used count. */
  336.           }        /* if valid digit */
  337.       }            /* for each digit */
  338.       }
  339.  
  340.       /*
  341.        * Digits_binary_low[] properly encodes the value of the digits.
  342.        * Forget about any high-order littlenums that are 0.
  343.        */
  344.       while (digits_binary_low [size_of_digits_in_littlenums - 1] == 0)
  345.     {
  346.       size_of_digits_in_littlenums --;
  347.     }
  348.  
  349.       digits_flonum . low    = digits_binary_low;
  350.       digits_flonum . high    = digits_binary_low + size_of_digits_in_littlenums - 1;
  351.       digits_flonum . leader    = digits_flonum . high;
  352.       digits_flonum . exponent    = 0;
  353.       /*
  354.        * The value of digits_flonum . sign should not be important.
  355.        * We have already decided th output's sign.
  356.        * We trust that the sign won't influence the other parts of the number!
  357.        * So we give it a value for these reasons:
  358.        * (1) courtesy to humans reading/debugging
  359.        *     these numbers so they don't get excited about strange values
  360.        * (2) in future there may be more meaning attached to sign,
  361.        *     and what was
  362.        *     harmless noise may become disruptive, ill-conditioned (or worse)
  363.        *     input.
  364.        */
  365.       digits_flonum . sign    = '+';
  366.  
  367.       {
  368.     /*
  369.      * Compute the mantssa (& exponent) of the power of 10.
  370.      * If sucessful, then multiply the power of 10 by the digits
  371.      * giving return_binary_mantissa and return_binary_exponent.
  372.      */
  373.  
  374.     LITTLENUM_TYPE *power_binary_low;
  375.     int        decimal_exponent_is_negative;
  376.                 /* This refers to the "-56" in "12.34E-56". */
  377.                 /* FALSE: decimal_exponent is positive (or 0) */
  378.                 /* TRUE:  decimal_exponent is negative */
  379.     FLONUM_TYPE    temporary_flonum;
  380.     LITTLENUM_TYPE *temporary_binary_low;
  381.     int        size_of_power_in_littlenums;
  382.     int        size_of_power_in_chars;
  383.  
  384.     size_of_power_in_littlenums = precision;
  385. /* Precision has a built-in fudge factor so we get a few guard bits. */
  386.  
  387.  
  388.     decimal_exponent_is_negative = decimal_exponent < 0;
  389.     if (decimal_exponent_is_negative)
  390.       {
  391.         decimal_exponent = - decimal_exponent;
  392.       }
  393.     /* From now on: the decimal exponent is > 0. Its sign is seperate. */
  394.     
  395.     size_of_power_in_chars
  396.       =   size_of_power_in_littlenums
  397.         * sizeof( LITTLENUM_TYPE );
  398.     power_binary_low = (LITTLENUM_TYPE *) alloca ( size_of_power_in_chars );
  399.     temporary_binary_low = (LITTLENUM_TYPE *) alloca ( size_of_power_in_chars );
  400.     bzero ((char *)power_binary_low, size_of_power_in_chars);
  401.     * power_binary_low = 1;
  402.     power_of_10_flonum . exponent    = 0;
  403.     power_of_10_flonum . low    = power_binary_low;
  404.     power_of_10_flonum . leader    = power_binary_low;
  405.     power_of_10_flonum . high    = power_binary_low    + size_of_power_in_littlenums - 1;
  406.     power_of_10_flonum . sign    = '+';
  407.     temporary_flonum . low    = temporary_binary_low;
  408.     temporary_flonum . high    = temporary_binary_low        + size_of_power_in_littlenums - 1;
  409.     /*
  410.      * (power) == 1.
  411.      * Space for temporary_flonum allocated.
  412.      */
  413.     
  414.     /*
  415.      * ...
  416.      *
  417.      * WHILE    more bits
  418.      * DO    find next bit (with place value)
  419.      *    multiply into power mantissa
  420.      * OD
  421.      */
  422.     {
  423.       int        place_number_limit;
  424.                 /* Any 10^(2^n) whose "n" exceeds this */
  425.                 /* value will fall off the end of */
  426.                 /* flonum_XXXX_powers_of_ten[]. */
  427.       int        place_number;
  428.       FLONUM_TYPE * multiplicand; /* -> 10^(2^n) */
  429.  
  430.       place_number_limit = table_size_of_flonum_powers_of_ten;
  431.       multiplicand
  432.         = (  decimal_exponent_is_negative
  433.            ? flonum_negative_powers_of_ten
  434.            : flonum_positive_powers_of_ten);
  435.       for (place_number = 1;    /* Place value of this bit of exponent. */
  436.            decimal_exponent;    /* Quit when no more 1 bits in exponent. */
  437.            decimal_exponent >>= 1
  438.            , place_number ++)
  439.         {
  440.           if (decimal_exponent & 1)
  441.         {
  442.           if (place_number > place_number_limit)
  443.             {
  444.               /*
  445.                * The decimal exponent has a magnitude so great that
  446.                * our tables can't help us fragment it.  Although this
  447.                * routine is in error because it can't imagine a
  448.                * number that big, signal an error as if it is the
  449.                * user's fault for presenting such a big number.
  450.                */
  451.               return_value = ERROR_EXPONENT_OVERFLOW;
  452.               /*
  453.                * quit out of loop gracefully
  454.                */
  455.               decimal_exponent = 0;
  456.             }
  457.           else
  458.             {
  459. #ifdef TRACE
  460. printf("before multiply, place_number = %d., power_of_10_flonum:\n", place_number);
  461. flonum_print( & power_of_10_flonum );
  462. (void)putchar('\n');
  463. #endif
  464.               flonum_multip (multiplicand + place_number, & power_of_10_flonum, & temporary_flonum);
  465.               flonum_copy (& temporary_flonum, & power_of_10_flonum);
  466.             }        /* If this bit of decimal_exponent was computable.*/
  467.         }            /* If this bit of decimal_exponent was set. */
  468.         }            /* For each bit of binary representation of exponent */
  469. #ifdef TRACE
  470. printf( " after computing power_of_10_flonum: " );
  471. flonum_print( & power_of_10_flonum );
  472. (void)putchar('\n');
  473. #endif
  474.     }
  475.  
  476.       }
  477.  
  478.       /*
  479.        * power_of_10_flonum is power of ten in binary (mantissa) , (exponent).
  480.        * It may be the number 1, in which case we don't NEED to multiply.
  481.        *
  482.        * Multiply (decimal digits) by power_of_10_flonum.
  483.        */
  484.  
  485.       flonum_multip (& power_of_10_flonum, & digits_flonum, address_of_generic_floating_point_number);
  486.       /* Assert sign of the number we made is '+'. */
  487.       address_of_generic_floating_point_number -> sign = digits_sign_char;
  488.  
  489.     }                /* If we had any significant digits. */
  490.   return (return_value);
  491. }                /* atof_generic () */
  492.  
  493. /* end: atof_generic.c */
  494.